using CfgTable;
using IQIGame.Onigao.Framework;
using IQIGame.Onigao.GamePlay;

namespace IQIGame.Onigao.Logic
{
    /// <summary>
    /// 开始镜头移动（切屏）
    /// 参数1：1：切屏表id(LevelScreenSwitch.Id)
    /// </summary>
    public class ExecStartCameraMotion : BaseServiceExecution
    {
        private const int WhileSafeEnsureCount = 100;
        public override void Execute(LevelRegion region, LevelPlayer player)
        {
            if (player != null && player.entity.isOccupied)
            {
                LogicLog.LogError("玩家正被其他动作占用。");
                return;
            }
            //如果切屏由系统触发（比如关卡时间，实体buff等），单人模式下需要专门去找到玩家，多人模式不能由系统触发，报错。
            if (player == null)
            {
                if (region.level.players.Count == 1)
                {
                    player = region.level.players[0];
                }
                else
                {
                    LogicLog.LogError("当前模式下（如多人模式），镜头动画只能由玩家主动触发。");
                    return;
                }
            }

            var config = _config as ExecParamCameraMotion;

            int screenSwitchCid = config.screenSwitchCid;
            player.isTakenOverBySystem = true;
            player.entity.OccupiedBy(EntityOccupationStatus.CameraMotion, screenSwitchCid, triggerEntity);
            triggerEntity?.OccupiedBy(EntityOccupationStatus.CameraMotion, screenSwitchCid);

            int totalDelay = 0;
            int safeEnsureCount = 0;
            int nextCid = screenSwitchCid;
            do
            {
                CfgLevelScreenSwitch cfgScreenSwitch = TableCenter.levelScreenSwitch.Get(nextCid);
                //计算单次镜头动画时长
                int lifeTimeMiliSec = cfgScreenSwitch.MoveTime + cfgScreenSwitch.Duration;
                int delayFrame = LgLevelConvertUtil.MillisecToFrame(lifeTimeMiliSec);
                //计算镜头动画总时长
                totalDelay += delayFrame;
                //如果有服务，设置延迟服务
                for (int i = 0; i < cfgScreenSwitch.EndService.Count; i++)
                {
                    //程序后台延迟服务（不走策划配置的延迟服务）
                    region.level.delayServiceMgr.AddBackendService(player, triggerEntity,
                        cfgScreenSwitch.EndService[i],
                        DelayServiceCondition.Realtime, totalDelay,
                        cfgScreenSwitch.IsSaveDelayService);
                }
                //safe ensure
                safeEnsureCount++;
                if (safeEnsureCount > WhileSafeEnsureCount)
                {
                    LogicLog.LogError($"镜头移动步骤超过{WhileSafeEnsureCount}步，请检查是否配置出现循环。");
                    break;
                }
                nextCid = cfgScreenSwitch.JumpId;
            }
            while (nextCid > 0);

            //延迟行为：释放占用
            var cameraDelayAction = ClassPool.Get<LevelReleaseOccupationDelayAction>();
            //totalDelay - 1是因为要保证释放占用在最后一个服务执行之前，否则最后一个服务可能会被其本身的占用阻碍。
            cameraDelayAction.Initialize(player, triggerEntity, totalDelay - 1, EntityOccupationStatus.CameraMotion);
            region.level.delayActionMgr.AddDelayAction(cameraDelayAction);

            region.NotifyStartCameraMotion(player, screenSwitchCid);
        }
    }
}
